package cc.rengu.igas.cops.core.service.trans.unionpay;


import cc.rengu.igas.channel.upqc.facade.request.C2BAddDealNoticeRequest;
import cc.rengu.igas.channel.upqc.facade.response.C2BAddDealNoticeResponse;
import cc.rengu.igas.channel.upqc.facade.result.Result;
import cc.rengu.igas.cops.common.enums.RespCodeEnum;
import cc.rengu.igas.cops.facade.request.BankC2bAddDealNoticeRequest;
import cc.rengu.igas.cops.facade.response.BankC2bAddDealNoticeResponse;
import cc.rengu.oltp.service.base.BizBaseService;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.MchntOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.PayOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.TxnLimitStatisMapper;
import cc.rengu.oltp.service.common.dao.UserOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.MchntOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.PayOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.TxnLimitStatisMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.UserOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.*;
import cc.rengu.oltp.service.common.enums.*;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.OrderInfo;
import cc.rengu.oltp.service.model.RiskMonitorInfo;
import cc.rengu.oltp.service.realize.DubboService;
import cc.rengu.oltp.service.realize.OrderService;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.TransCustomImpl;
import cc.rengu.oltp.service.realize.impl.DubboServiceImpl;
import cc.rengu.oltp.service.realize.impl.OrderServiceImpl;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.BeanUtil;
import cc.rengu.oltp.utility.util.ConvertUtil;
import cc.rengu.oltp.utility.util.DateUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;
import cc.rengu.utility.reflect.JsonUtil;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;

/**
 * 被扫---认证完毕通知
 * 手机银行【ESB】—>支付系统—>通道—>银联
 * <p>
 * BizStatus：
 * 01-业务处理中
 * 40-授权未完成【待密码认证】
 * 41-授权已完成【密码验证完成】
 * 订单表字段：
 * remark1：预授权状态
 * remark2:付款凭证号
 * remark3：被扫-付款人信息
 * frontBackUrl：值为【Speline】时表示是七里堡POS扫码
 * front_seq_num前端流水号：付款凭证号
 * group_mchnt_no：商户号-七里堡扫码时送商户号
 * need_pay_amt：扫码收款金额
 *
 * @author panky
 * @version 1.0.0 创建时间：2020.06.18
 */
public class BankC2bAddDealNoticeService extends BizBaseService implements TransCustomImpl {

    @Override
    protected Object beforeBizProcess() throws Exception {
        BankC2bAddDealNoticeRequest bankGenC2BNoRequest = new BankC2bAddDealNoticeRequest();
        ConvertUtil.convertOutput(bankGenC2BNoRequest);
        return bankGenC2BNoRequest;
    }

    @Override
    protected BizResponse callBizService(Object request) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        // 录入参数
        BankC2bAddDealNoticeRequest bankC2bAddDealNoticeRequest = (BankC2bAddDealNoticeRequest) request;
        // 行号
        String instId = bankC2bAddDealNoticeRequest.getHeader().getInstId();

        if (bankC2bAddDealNoticeRequest.getHeader().getChanlId().equals("UPQC")) {
            bankC2bAddDealNoticeRequest.getHeader().setChanlId("03");
        }

        UserOrderInfoMapper userOrderInfoMapper = new UserOrderInfoMapperImpl();
        UserOrderInfo userOrderInfo = userOrderInfoMapper.selectUserOrderInfoByOrderUrl(instId, bankC2bAddDealNoticeRequest.getQrNo());

        if (null == userOrderInfo) {
            rglog.debug("查询用户订单表异常");
            throw new BizException(OltpRpcdEnum.RECOND_EMPTY_OR_NOT_FOUND.getRespCode(), OltpRpcdEnum.RECOND_EMPTY_OR_NOT_FOUND.getRespDesc());
        }
        // 更新业务状态，已经认证完成
        userOrderInfo.setBizStatus(BizStatusEnum.AUTH_COMPLETE.getStatus());

        OrderService orderService = new OrderServiceImpl();
        // 更新状态
        boolean isOrderCode = orderService.updateOrderInfo(userOrderInfo, null, null);
        if (!isOrderCode) {
            rglog.error("更新用户订单表失败!");
            throw new BizException(RespCodeEnum.UPDATE_ORDER_ERROR.getRespCode(), RespCodeEnum.ORDER_NOEXIT.getRespDesc());
        }

        SysParamService sysParamService = new SysParamServiceImpl();
        /* 银联码，获取法人行在银联的机构号 */
        SysParam unionPayCode = sysParamService.getSysParamInfo(instId, "OPMS_SYS_PARAM", "unionPayerOrgCode" + "_" + bankC2bAddDealNoticeRequest.getHeader().getChanlId());
        if (null == unionPayCode) {
            rglog.error("获取二维码服务失败！获取法人行在银联的机构号失败！instId:{}", instId);
            throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
        }
        // 银联机构号
        String strUnonPayCode = unionPayCode.getParamValue();
        C2BAddDealNoticeRequest c2bAddDealNoticeRequest = new C2BAddDealNoticeRequest();
        // 银联机构号	issInsCode
        c2bAddDealNoticeRequest.setIssInsCode(strUnonPayCode);
        // 凭证号	voucherNum	String	20	M
        c2bAddDealNoticeRequest.setVoucherNum(userOrderInfo.getFrontSeqNum());
        // 订单号	orderId
        c2bAddDealNoticeRequest.setOrderId(userOrderInfo.getSysSeqNum());
        //订单发送时间	orderTime
        c2bAddDealNoticeRequest.setOrderTime(userOrderInfo.getOrderCreateTime());
        // c2b码
        c2bAddDealNoticeRequest.setPayQrCode(bankC2bAddDealNoticeRequest.getQrNo());

        c2bAddDealNoticeRequest.setRespCode("00");
        c2bAddDealNoticeRequest.setRespDesc("交易成功");

        cc.rengu.igas.channel.upqc.facade.base.Header upHeader = new cc.rengu.igas.channel.upqc.facade.base.Header();
        BeanUtil.beanCopy(bankC2bAddDealNoticeRequest.getHeader(), upHeader);

        upHeader.setTxnNum("0240000903");// 查询订单
        upHeader.setSrcSysId("OPMS");
        c2bAddDealNoticeRequest.setHeader(upHeader);
        DubboService dubboService = new DubboServiceImpl();
        Result<C2BAddDealNoticeResponse> responseResult = (Result<C2BAddDealNoticeResponse>) dubboService.callDubboService("upqcPayerService", "c2bAddDealNotice", c2bAddDealNoticeRequest);
        if (null == responseResult || !responseResult.isSuccess() || !"00000000".equals(responseResult.getResult().getRespCode())) {
            rglog.error("调用银联二维码验证完毕失败，二维码<{}>信息失败,iReturnCode:<{}>", userOrderInfo.getSysSeqNum(),
                    responseResult.getResult().getRespCode());
            throw new BizException(RespCodeEnum.GET_QRCODE_INFO_ERROR.getRespCode(), RespCodeEnum.GET_QRCODE_INFO_ERROR.getRespDesc());
        }

        BankC2bAddDealNoticeResponse bankC2bAddDealNoticeResponse = new BankC2bAddDealNoticeResponse();
        // 返回
        BizResponse bizResponse = new BizResponse();
        bizResponse.setResult(bankC2bAddDealNoticeResponse);// 返回结果
        bizResponse.setRspSysId(AppParamConstant.IGAS);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        return bizResponse;
    }

    @Override
    protected void afterBizProcess(BizResponse response) throws Exception {
        BankC2bAddDealNoticeResponse bankGenC2BNoResponse = (BankC2bAddDealNoticeResponse) response.getResult();
        ConvertUtil.convertInput(bankGenC2BNoResponse);
    }

    @Override
    protected RiskMonitorInfo getRiskMonitorInfo() {
        return null;
    }

    /**
     * 更改订单状态
     *
     * @param bankC2bAddDealNoticeRequest 接口请求对象
     * @param transStatus                 交易状态:0-初始状态     * 1-交易成功     * 2-交易失败     * 3-交易超时"
     * @return 更改结果, true-成功|false-失败
     * @throws Exception 异常信息
     */
    private boolean isUpdateOrderStatus(BankC2bAddDealNoticeRequest bankC2bAddDealNoticeRequest, String transStatus) throws Exception {
        rglog.info("开始更改订单状态,交易结果:<{}>", transStatus);
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String instId = bankC2bAddDealNoticeRequest.getHeader().getInstId();
        String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue("speLineSysSeqNum");
        String updateTime = DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS");

        //region 查询、更新 用户订单、商户订单、支付订单
        /*用户订单*/
        UserOrderInfoMapper userOrderInfoMapper = new UserOrderInfoMapperImpl();
        UserOrderInfo userOrderInfo = userOrderInfoMapper.selectUserOrderInfoByPrimaryKey(instId, sysSeqNum);
        if (userOrderInfo == null) {
            throw new BizException(RespCodeEnum.NONFINANCIALCURRENT_ERROR.getRespCode(), RespCodeEnum.NONFINANCIALCURRENT_ERROR.getRespDesc());
        }
        rglog.debug("查询用户订单:<{}>", JsonUtil.toJson(userOrderInfo));
        if (TransStatusEnum.TRANS_SUCC.getStatus().equals(transStatus)) {
            //成功
            userOrderInfo.setOrderStatus(OrderStatusEnum.FINISH.getStatus());
            userOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
        } else if (TransStatusEnum.TRANS_TIMEOUT.getStatus().equals(transStatus)) {
            //超时/未知
            userOrderInfo.setOrderStatus(OrderStatusEnum.INIT.getStatus());
            userOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
        } else {
            //失败
            userOrderInfo.setOrderStatus(OrderStatusEnum.CLOSE.getStatus());
            userOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
        }
        userOrderInfo.setTransStatus(transStatus);
        userOrderInfo.setUpdateTime(updateTime);

        /*商户订单*/
        MchntOrderInfoMapper mchntOrderInfoMapper = new MchntOrderInfoMapperImpl();
        List<MchntOrderInfo> mchntOrderInfoList = mchntOrderInfoMapper.selectMchntOrderInfoBySysSeqNum(instId, sysSeqNum);
        if (null == mchntOrderInfoList || mchntOrderInfoList.size() == 0 || null == mchntOrderInfoList.get(0)) {
            throw new BizException(RespCodeEnum.NONFINANCIALCURRENT_ERROR.getRespCode(), RespCodeEnum.NONFINANCIALCURRENT_ERROR.getRespDesc());
        }
        MchntOrderInfo mchntOrderInfo = mchntOrderInfoList.get(0);
        rglog.debug("查询商户订单:<{}>", JsonUtil.toJson(mchntOrderInfo));
        mchntOrderInfo.setTransStatus(transStatus);
        mchntOrderInfo.setUpdateTime(updateTime);

        /*支付订单*/
        PayOrderInfoMapper payOrderInfoMapper = new PayOrderInfoMapperImpl();
        List<PayOrderInfo> payOrderInfoList = payOrderInfoMapper.selectPayOrderInfoBySysSeqNum(instId, sysSeqNum);
        if (null == payOrderInfoList || payOrderInfoList.size() != 1 || null == payOrderInfoList.get(0)) {
            throw new BizException(RespCodeEnum.NONFINANCIALCURRENT_ERROR.getRespCode(), RespCodeEnum.NONFINANCIALCURRENT_ERROR.getRespDesc());
        }
        PayOrderInfo payOrderInfo = payOrderInfoList.get(0);
        rglog.debug("查询支付订单:<{}>", JsonUtil.toJson(payOrderInfo));
        payOrderInfo.setTransStatus(transStatus);
        payOrderInfo.setUpdateTime(updateTime);
        if (TransStatusEnum.TRANS_SUCC.getStatus().equals(transStatus)) {
            //调用成功记录ESB支付通道流水号
            String channelSeqNum = xmlTreeUtil.getXmlTreeStringValue("esbChannelSeqNum");
            payOrderInfo.setChannelSeqNum(channelSeqNum);
            payOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
        } else if (TransStatusEnum.TRANS_TIMEOUT.getStatus().equals(transStatus)) {
            //超时/未知
            payOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
        } else {
            //失败
            payOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
        }
        //endregion

        OrderService orderService = new OrderServiceImpl();
        return orderService.updateOrderInfo(userOrderInfo, Arrays.asList(mchntOrderInfo), payOrderInfo);
    }

    //region 更新用户限额、商户限额

    /**
     * 更新用户限额
     *
     * @return Boolean 更新结果
     * @throws Exception 异常信息
     */
    private boolean isUpDateUserLimit() throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String instId = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.INST_ID);
        UserOrderInfo userOrderInfo = (UserOrderInfo) xmlTreeUtil.getXmlTreeObjectValue("qrCodeUserOrderInfo", UserOrderInfo.class);
        String payerUserId = userOrderInfo.getUserId();
        String mechNoAndCstNo = instId + "|" + payerUserId;
        TxnLimitStatisMapper txnLimitStatisMapper = new TxnLimitStatisMapperImpl();
        TxnLimitStatis txnLimitStatis = txnLimitStatisMapper.selectTxnLimitStatisByPrimaryKey(instId,
                DateUtil.getCurrentDate(), // 当前日期
                "D", // 日累计
                LimitTypeEnum.C2B_QR.getLimitType() + mechNoAndCstNo + "*");// 限额类型 + 限额主体 + 限额账户类型

        if (null == txnLimitStatis) {
            rglog.error("获取用户限额信息失败.");
            return false;
        }
        String transAmt = txnLimitStatis.getTotalTransAmt();
        int transNum = txnLimitStatis.getTotalTransNum();
        txnLimitStatis.setTotalTransAmt(new BigDecimal(transAmt).add(new BigDecimal(userOrderInfo.getNeedPayAmt())).toString());
        txnLimitStatis.setTotalTransNum(++transNum);

        if (0 == txnLimitStatisMapper.updateTxnLimitStatisByPrimaryKey(txnLimitStatis)) {
            return true;
        }
        return false;
    }

    @Override
    public ChannelCallCfg channelCallSceneDiscern(Object request, List<ChannelCallCfg> channelCallCfgList) throws Exception {
        return null;
    }

    @Override
    public CheckResultEnum channelCallPreCheck(Object request, ChannelCallCfg channelCallCfg, OrderInfo orderInfo) throws Exception {
        return null;
    }

    @Override
    public TransStatusEnum channelCallResultProc(Object request, ChannelCallCfg channelCallCfg, TransStatusEnum transStatusEnum, Object channelResponse, OrderInfo needUpdateOrderInfo) throws Exception {
        return null;
    }
}
